home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.92
/
crossfir
/
crossfire-0.92.5
/
common
/
item.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-24
|
23KB
|
804 lines
/*
* static char *rcsid_item_c =
* "$Id: item.c,v 1.35 1996/07/24 07:01:37 master Exp master $";
*/
/*
CrossFire, A Multiplayer game for X-windows
Copyright (C) 1992 Frank Tore Johansen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author can be reached via e-mail to frankj@ifi.uio.no.
*/
#include <global.h>
#include <funcpoint.h>
#include <living.h>
#define DESCRIBE_ABILITY(retbuf, variable, name) \
if(variable) { \
int i,j=0; \
strcat(retbuf,"(" name ": "); \
for(i=0; i<NROFATTACKS; i++) \
if(variable & (1<<i)) { \
if (j) \
strcat(retbuf,", "); \
else \
j = 1; \
strcat(retbuf, attacks[i]); \
} \
strcat(retbuf,")"); \
}
extern char *spellpathnames[NRSPELLPATHS];
static char numbers[21][20] = {
"no","a","two","three","four","five","six","seven","eight","nine","ten",
"eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen",
"eighteen","nineteen","twenty"
};
static char numbers_10[10][20] = {
"zero","ten","twenty","thirty","fourty","fifty","sixty","seventy",
"eighty","ninety"
};
static char levelnumbers[21][20] = {
"zeroth","first", "second", "third", "fourth", "fifth", "sixth", "seventh",
"eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth",
"fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteen",
"nineteen", "twentieth"
};
static char levelnumbers_10[11][20] = {
"zeroth","tenth","twentieth","thirtieth","fortieth","fiftieth","sixtieth",
"seventieth","eightieth","ninetieth"
};
extern spell spells[NROFREALSPELLS];
/*
* query_weight(object) returns a character pointer to a static buffer
* containing the text-representation of the weight of the given object.
* The buffer will be overwritten by the next call to query_weight().
*/
char *query_weight(object *op) {
static char buf[10];
int i=op->nrof?op->nrof*op->weight:op->weight+op->carrying;
if(op->weight<0)
return " ";
if(i%1000)
sprintf(buf,"%6.1f",i/1000.0);
else
sprintf(buf,"%4d ",i/1000);
return buf;
}
/*
* Returns the pointer to a static buffer containing
* the number requested (of the form first, second, third...)
*/
char *get_levelnumber(int i) {
static char buf[MAX_BUF];
if (i > 99) {
sprintf(buf, "%d.", i);
return buf;
}
if(i < 21)
return levelnumbers[i];
if(!(i%10))
return levelnumbers_10[i/10];
strcpy(buf, numbers_10[i/10]);
strcat(buf, levelnumbers[i%10]);
return buf;
}
/*
* get_number(integer) returns the text-representation of the given number
* in a static buffer. The buffer might be overwritten at the next
* call to get_number().
* It is currently only used by the query_name() function.
*/
char *get_number(int i) {
if(i<=20)
return numbers[i];
else {
static char buf[MAX_BUF];
sprintf(buf,"%d",i);
return buf;
}
}
/*
* Returns pointer to static buffer containing ring's or amulet's
* abilities
* These are taken from old query_name(), but it would work better
* if describle_item() would be called to get this information and
* caller would handle FULL_RING_DESCRIPTION definition.
* Or make FULL_RING_DESCRIPTION standard part of a game and let
* client handle names.
*/
/* Aug 95 modified this slightly so that Skill tools don't have magic bonus
* from stats.sp - b.t.
*/
char *ring_desc (object *op)
{
static char buf[MAX_BUF];
int attr, val;
buf[0] = 0;
if (! QUERY_FLAG(op, FLAG_IDENTIFIED))
return buf;
for (attr=0; attr<7; attr++) {
if ((val=get_attr_value(&(op->stats),attr))!=0) {
sprintf (buf+strlen(buf), "(%s%+d)", short_stat_name[attr], val);
}
}
if(op->stats.exp)
sprintf(buf+strlen(buf), "(speed %+d)", op->stats.exp);
if(op->stats.wc)
sprintf(buf+strlen(buf), "(wc%+d)", op->stats.wc);
if(op->stats.dam)
sprintf(buf+strlen(buf), "(dam%+d)", op->stats.dam);
if(op->stats.ac)
sprintf(buf+strlen(buf), "(ac%+d)", op->stats.ac);
if(op->armour)
sprintf(buf+strlen(buf), "(armour%+d)", op->armour);
if (op->stats.food > 0)
sprintf(buf+strlen(buf), "(sustenance%+d)", op->stats.food);
else if (op->stats.food < 0)
sprintf(buf+strlen(buf), "(hunger%+d)", op->stats.food);
if(op->stats.sp && op->type!=SKILL)
sprintf(buf+strlen(buf), "(magic%+d)", op->stats.sp);
if(op->stats.hp)
sprintf(buf+strlen(buf), "(regeneration%+d)", op->stats.hp);
if(op->stats.luck)
sprintf(buf+strlen(buf), "(luck%+d)", op->stats.luck);
if(QUERY_FLAG(op,FLAG_LIFESAVE))
strcat(buf,"(lifesaving)");
if(QUERY_FLAG(op,FLAG_REFL_SPELL))
strcat(buf,"(reflect spells)");
if(QUERY_FLAG(op,FLAG_REFL_MISSILE))
strcat(buf,"(reflect missiles)");
if(QUERY_FLAG(op,FLAG_STEALTH))
strcat(buf,"(stealth)");
/* Shorten some of the names, so they appear better in the windows */
DESCRIBE_ABILITY(buf, op->immune, "Immune");
DESCRIBE_ABILITY(buf, op->protected, "Pro");
DESCRIBE_ABILITY(buf, op->vulnerable, "Vuln");
DESCRIBE_PATH(buf, op->path_attuned, "Attuned");
DESCRIBE_PATH(buf, op->path_repelled, "Repelled");
DESCRIBE_PATH(buf, op->path_denied, "Denied");
if(buf[0] == 0 && op->type!=SKILL)
strcpy(buf,"of adornment");
return buf;
}
/*
* query_short_name(object) is similar to query_name, but doesn't
* contain any information about object status (worn/cursed/etc.)
*/
char *query_short_name(object *op)
{
static char buf[MAX_BUF];
char buf2[MAX_BUF];
if(op->name == NULL)
return "(null)";
if(!op->nrof && !op->weight && !op->title && !is_magical(op))
return op->name; /* To speed things up (or make things slower?) */
if(op->nrof) {
strcpy(buf, get_number(op->nrof));
/* if nrof==1, then get_number returns 'a'. Add an 'n' if appropriate*/
if(op->nrof==1&&QUERY_FLAG(op,FLAG_AN))
strcat(buf,"n");
strcat(buf, " ");
strcat(buf,op->name);
if (op->nrof != 1) {
char *buf3 = strstr(buf, " of ");
if (buf3!=NULL) {
strcpy(buf2, buf3);
*buf3 = '\0'; /* also changes value in buf */
}
if(QUERY_FLAG(op,FLAG_NEED_IE)) {
char *cp=strrchr(buf,'y');
if(cp!=NULL)
*cp='\0'; /* Strip the 'y' */
strcat(buf,"ies");
} else if (buf[strlen(buf)-1]!='s')
/* if the item ends in 's', then adding another one is
* not the way to pluralize it. The only item where this
* matters (that I know of) is bracers, as they start of
* plural
*/
strcat(buf,"s");
/* If buf3 is set, then this was a string that contained
* something of something (potion of dexterity.) The part before
* the of gets made plural, so now we need to copy the rest
* (after and including the " of "), to the buffer string.
*/
if (buf3)
strcat(buf, buf2);
}
} else {
/* if nrof is 0, the object is not mergable, and thus, op->name
should contain the name to be used. */
strcpy(buf,op->name);
}
if (op->title && QUERY_FLAG(op,FLAG_IDENTIFIED)) {
strcat(buf, " ");
strcat(buf, op->title);
}
switch(op->type) {
case SCROLL:
case WAND:
case SPELLBOOK:
case ROD:
if (QUERY_FLAG(op,FLAG_IDENTIFIED)||QUERY_FLAG(op,FLAG_BEEN_APPLIED)) {
if(!op->title) {
strcat(buf," of ");
strcat(buf,spells[op->stats.sp].name);
if(op->type != SPELLBOOK)
sprintf(buf+strlen(buf), " (lvl %d)", op->level);
}
}
break;
case SKILL:
case AMULET:
case RING:
#ifdef FULL_RING_DESCRIPTION
if (!op->title) {
/* If ring has a title, full description isn't so useful */
char *s = ring_desc(op);
if (s[0]) {
strcat (buf, " ");
strcat (buf, s);
}
}
#endif
break;
default:
if(op->magic && ((QUERY_FLAG(op,FLAG_BEEN_APPLIED) &&
need_identify(op)) || QUERY_FLAG(op,FLAG_IDENTIFIED))) {
sprintf(buf + strlen(buf), " %+d", op->magic);
}
}
return buf;
}
/*
* query_name(object) returns a character pointer pointing to a static
* buffer which contains a verbose textual representation of the name
* of the given object. The buffer will be overwritten at the next
* call to query_name().
*/
char *query_name(object *op) {
static char buf[MAX_BUF];
strcpy (buf, query_short_name(op));
if (QUERY_FLAG(op,FLAG_INV_LOCKED))
strcat(buf, " *");
if (op->type == CONTAINER && ((op->env && op->env->container == op) ||
(!op->env && QUERY_FLAG(op,FLAG_APPLIED))))
strcat(buf," (open)");
if (QUERY_FLAG(op,FLAG_KNOWN_CURSED)) {
if(QUERY_FLAG(op,FLAG_DAMNED))
strcat(buf, " (damned)");
else if(QUERY_FLAG(op,FLAG_CURSED))
strcat(buf, " (cursed)");
}
/* Basically, if the object is known magical (detect magic spell on it),
* and it isn't identified, print out the fact that
* it is magical. Assume that the detect magical spell will only set
* KNOWN_MAGICAL if the item actually is magical.
*
* Changed in V 0.91.4 - still print that the object is magical even
* if it has been applied. Equipping an item does not tell full
* abilities, especially for artifact items.
*/
if (QUERY_FLAG(op,FLAG_KNOWN_MAGICAL) && !QUERY_FLAG(op,FLAG_IDENTIFIED))
strcat(buf, " (magic)");
if(QUERY_FLAG(op,FLAG_APPLIED)) {
switch(op->type) {
case BOW:
case WAND:
case ROD:
case HORN:
strcat(buf," (readied)");
break;
case WEAPON:
strcat(buf," (wielded)");
break;
case ARMOUR:
case HELMET:
case SHIELD:
case RING:
case BOOTS:
case GLOVES:
case AMULET:
case GIRDLE:
case BRACERS:
case CLOAK:
strcat(buf," (worn)");
break;
case CONTAINER:
strcat(buf," (active)");
break;
case SKILL:
default:
strcat(buf," (applied)");
}
}
if(QUERY_FLAG(op, FLAG_UNPAID))
strcat(buf," (unpaid)");
return buf;
}
/*
* Returns a pointer to a static buffer which contains a
* description of the given object.
* If it is a monster, lots of information about its abilities
* will be returned.
* If it is an item, lots of information about which abilities
* will be gained about its user will be returned.
* If it is a player, it writes out the current abilities
* of the player, which is usually gained by the items applied.
*/
char *describe_item(object *op) {
char buf[MAX_BUF];
static char retbuf[VERY_BIG_BUF];
retbuf[0]='\0';
if(QUERY_FLAG(op,FLAG_MONSTER)) {
/* Merge: Should it be 0.01 instead of 0.001? CE 0.7 has the former*/
if(FABS(op->speed)>0.001) {
switch((int)((FABS(op->speed))*15)) {
case 0:
strcat(retbuf,"(very slow movement)");
break;
case 1:
strcat(retbuf,"(slow movement)");
break;
case 2:
strcat(retbuf,"(normal movement)");
break;
case 3:
case 4:
strcat(retbuf,"(fast movement)");
break;
case 5:
case 6:
strcat(retbuf,"(very fast movement)");
break;
case 7:
case 8:
case 9:
case 10:
strcat(retbuf,"(extremely fast movement)");
break;
default:
strcat(retbuf,"(lightning fast movement)");
break;
}
}
} else switch(op->type) {
case BOW:
case ARROW:
case WAND:
case ROD:
case HORN:
case PLAYER:
case WEAPON:
case ARMOUR:
case HELMET:
case SHIELD:
case BOOTS:
case GLOVES:
case GIRDLE:
case BRACERS:
case CLOAK:
break;
case SKILL:
case RING:
case AMULET:
#ifdef FULL_RING_DESCRIPTION
if (op->title)
strcat (retbuf, ring_desc(op));
#else
strcat (retbuf, ring_desc(op));
#endif
return retbuf;
default:
return retbuf;
}
if(op->type!=PLAYER && !QUERY_FLAG(op,FLAG_MONSTER)) {
if(!need_identify(op) || QUERY_FLAG(op,FLAG_IDENTIFIED) || QUERY_FLAG(op,FLAG_BEEN_APPLIED)) {
int attr,val;
for (attr=0; attr<7; attr++) {
if ((val=get_attr_value(&(op->stats),attr))!=0) {
sprintf(buf, "(%s%+d)", short_stat_name[attr], val);
strcat(retbuf,buf);
}
}
if(op->stats.exp) {
sprintf(buf,"(speed %+d)",op->stats.exp);
strcat(retbuf,buf);
}
switch(op->type) {
case BOW:
case ARROW:
case GIRDLE:
case HELMET:
case SHIELD:
case BOOTS:
case GLOVES:
case WEAPON:
case SKILL:
case RING:
case AMULET:
case ARMOUR:
case BRACERS:
case FORCE:
case CLOAK:
if(op->stats.wc) {
sprintf(buf,"(wc%+d)",op->stats.wc);
strcat(retbuf,buf);
}
if(op->stats.dam) {
sprintf(buf,"(dam%+d)",op->stats.dam);
strcat(retbuf,buf);
}
if(op->stats.ac) {
sprintf(buf,"(ac%+d)",op->stats.ac);
strcat(retbuf,buf);
}
break;
default:
break;
}
}
if(!need_identify(op) || QUERY_FLAG(op,FLAG_IDENTIFIED)) {
switch(op->type) {
case ROD: /* These use stats.sp for spell selection and stats.food */
case HORN: /* and stats.hp for spell-point regeneration... */
case BOW:
case ARROW:
case WAND:
break;
default:
if(op->stats.food) {
if(op->stats.food>0)
sprintf(buf,"(sustenance%+d)",op->stats.food);
else
sprintf(buf,"(hunger%+d)",op->stats.food);
strcat(retbuf,buf);
}
if(op->stats.sp) {
sprintf(buf,"(magic%+d)",op->stats.sp);
strcat(retbuf,buf);
}
if(op->stats.hp) {
sprintf(buf,"(regeneration%+d)",op->stats.hp);
strcat(retbuf,buf);
}
}
}
} else if(op->type == PLAYER) {
if(op->contr->digestion) {
if(op->contr->digestion>0)
sprintf(buf,"(sustenance%+d)",op->contr->digestion);
else
sprintf(buf,"(hunger%+d)",op->contr->digestion);
strcat(retbuf,buf);
}
if(op->contr->gen_sp) {
sprintf(buf,"(magic%+d)",op->contr->gen_sp);
strcat(retbuf,buf);
}
if(op->contr->gen_hp) {
sprintf(buf,"(regeneration%+d)",op->contr->gen_hp);
strcat(retbuf,buf);
}
}
if(!need_identify(op) || QUERY_FLAG(op,FLAG_IDENTIFIED) || QUERY_FLAG(op,FLAG_BEEN_APPLIED)) {
if(op->armour) {
sprintf(buf,"(armour%+d)",op->armour);
strcat(retbuf,buf);
}
if(QUERY_FLAG(op,FLAG_XRAYS))
strcat(retbuf,"(xray-vision)");
if(QUERY_FLAG(op,FLAG_FLYING))
strcat(retbuf,"(levitate)");
if(QUERY_FLAG(op,FLAG_SEE_IN_DARK))
strcat(retbuf,"(infravision)");
}
if(!need_identify(op) || QUERY_FLAG(op,FLAG_IDENTIFIED)) {
if(op->stats.luck) {
sprintf(buf,"(luck%+d)",op->stats.luck);
strcat(retbuf,buf);
}
if(QUERY_FLAG(op,FLAG_LIFESAVE))
strcat(retbuf,"(lifesaving)");
if(QUERY_FLAG(op,FLAG_REFL_SPELL))
strcat(retbuf,"(reflect spells)");
if(QUERY_FLAG(op,FLAG_REFL_MISSILE))
strcat(retbuf,"(reflect missiles)");
if(QUERY_FLAG(op,FLAG_STEALTH))
strcat(retbuf,"(stealth)");
if(op->slaying!=NULL) {
strcat(retbuf,"(slay ");
strcat(retbuf,op->slaying);
strcat(retbuf,")");
}
}
if(QUERY_FLAG(op,FLAG_MONSTER)) {
if(QUERY_FLAG(op,FLAG_UNDEAD))
strcat(retbuf,"(undead)");
if(QUERY_FLAG(op,FLAG_CAN_PASS_THRU))
strcat(retbuf,"(pass through doors)");
if(QUERY_FLAG(op,FLAG_SEE_INVISIBLE))
strcat(retbuf,"(see invisible)");
if(QUERY_FLAG(op,FLAG_USE_WEAPON))
strcat(retbuf,"(wield weapon)");
if(QUERY_FLAG(op,FLAG_USE_BOW))
strcat(retbuf,"(archer)");
if(QUERY_FLAG(op,FLAG_USE_ARMOUR))
strcat(retbuf,"(wear armour)");
if(QUERY_FLAG(op,FLAG_USE_RING))
strcat(retbuf,"(wear ring)");
if(QUERY_FLAG(op,FLAG_USE_SCROLL))
strcat(retbuf,"(read scroll)");
if(QUERY_FLAG(op,FLAG_USE_WAND))
strcat(retbuf,"(fire wand)");
if(QUERY_FLAG(op,FLAG_USE_ROD))
strcat(retbuf,"(use rod)");
if(QUERY_FLAG(op,FLAG_USE_HORN))
strcat(retbuf,"(use horn)");
if(QUERY_FLAG(op,FLAG_CAST_SPELL))
strcat(retbuf,"(spellcaster)");
if(QUERY_FLAG(op,FLAG_FRIENDLY))
strcat(retbuf,"(friendly)");
if(QUERY_FLAG(op,FLAG_UNAGGRESSIVE))
strcat(retbuf,"(unaggressive)");
if(QUERY_FLAG(op,FLAG_HITBACK))
strcat(retbuf,"(hitback)");
if(op->arch->randomitems != NULL) {
treasure *t;
int first = 1;
for(t=op->arch->randomitems->items; t != NULL; t=t->next)
if(t->item && (t->item->clone.type == ABILITY)) {
if(first) {
first = 0;
strcat(retbuf,"(Spell abilities:)");
}
strcat(retbuf,"(");
strcat(retbuf,t->item->clone.name);
strcat(retbuf,")");
}
}
}
if(!need_identify(op)||QUERY_FLAG(op,FLAG_IDENTIFIED)||
QUERY_FLAG(op,FLAG_MONSTER)) {
/* if (op->attacktype != 1)*/
DESCRIBE_ABILITY(retbuf, op->attacktype, "Attacks");
DESCRIBE_ABILITY(retbuf, op->immune, "Immune");
DESCRIBE_ABILITY(retbuf, op->protected, "Protected");
DESCRIBE_ABILITY(retbuf, op->vulnerable, "Vulnerable");
DESCRIBE_PATH(retbuf, op->path_attuned, "Attuned");
DESCRIBE_PATH(retbuf, op->path_repelled, "Repelled");
DESCRIBE_PATH(retbuf, op->path_denied, "Denied");
}
return retbuf;
}
/* Return true if the item is magical. A magical item is one that
* increases/decreases any abilities, provides protection, immunity,
* or vulnerability, has a generic magical bonus, or is an artifact.
* This function is used by detect_magic to determine if an item
* should be marked as magical.
*/
int is_magical(object *op) {
int i;
/* living creatures are considered non magical */
if (QUERY_FLAG(op, FLAG_ALIVE)) return 0;
/* This is a test for it being an artifact, as artifacts have titles
*/
if (op->title!=NULL) return 1;
/* Handle rings and amulets specially. If they change any of these
* values, it means they are magical.
*/
if ((op->type==AMULET || op->type==RING) &&
(op->stats.ac || op->stats.food || op->stats.exp || op->stats.dam ||
op->stats.wc || op->stats.sp || op->stats.hp || op->stats.luck))
return 1;
/* Take care of polished shield and helmet of xray vision */
if ((op->type==AMULET || op->type==SHIELD) && (QUERY_FLAG(op, FLAG_REFL_SPELL) ||
QUERY_FLAG(op, FLAG_REFL_MISSILE))) return 1;
if (op->type==HELMET && QUERY_FLAG(op,FLAG_XRAYS)) return 1;
/* Potions, rods & boots are always magical. Wands/staves are also magical,
* assuming they still have any charges left.
*/
if (op->type==POTION || op->type==ROD || op->type==BOOTS ||
(op->type==WAND && op->stats.food)) return 1;
/* if something protects, immunes or vulnerables, it must be magical.
* power crystal, spellbooks, and scrolls are always magical.
*/
if (op->immune || op->protected || op->vulnerable || op->magic ||
op->type==POWER_CRYSTAL || op->type==SPELLBOOK || op->type==SCROLL)
return 1;
/* Check to see if it increases/decreases any stats */
for (i=0; i<7; i++)
if (get_attr_value(&(op->stats),i)!=0) return 1;
/* If it doesn't fall into any of the above categories, must
* be non magical.
*/
return 0;
}
int always_magical(object *op) {
switch(op->type) {
case RING:
case BRACERS:
case BOOTS: /* For now at least */
case GLOVES: /* ditto */
case AMULET:
case GIRDLE:
case ROD:
case SCROLL:
case SPELLBOOK:
case POTION:
return 1;
case WAND:
if (op->stats.food)
return 1;
}
return 0;
}
/* need_identify returns true if the item should be identified. This
* function really should not exist - by default, any item not identified
* should need it.
*/
int need_identify(object *op) {
switch(op->type) {
case RING:
case WAND:
case ROD:
case HORN:
case SCROLL:
case SKILL:
case SKILLSCROLL:
case SPELLBOOK:
case FOOD:
case POTION:
case BOW:
case ARROW:
case WEAPON:
case ARMOUR:
case SHIELD:
case HELMET:
case AMULET:
case BOOTS:
case GLOVES:
case BRACERS:
case GIRDLE:
case CONTAINER:
case DRINK:
case FLESH:
case INORGANIC:
case CLOSE_CON:
case CLOAK:
case GEM:
case POWER_CRYSTAL:
return 1;
}
/* Try to track down some stuff that may show up here. Thus, the
* archetype file can be updated, and this function removed.
*/
#if 0
LOG(llevDebug,"need_identify: %s does not need to be id'd\n", op->name);
#endif
return 0;
}
/*
* Return the number of the spell that whose name passes the pasesed string
* argument. Return -1 if no such spell name match is found.
*/
int look_up_spell_name( char * spname ){
register int i;
for(i=0;i< NROFREALSPELLS;i++){
if( strcmp(spname, spells[i].name) == 0) return i;
}
return -1;
}
/*
* Supposed to fix face-values as well here, but later.
*/
void identify(object *op) {
SET_FLAG(op,FLAG_IDENTIFIED);
CLEAR_FLAG(op, FLAG_KNOWN_MAGICAL);
/*
* We want autojoining of equal objects:
*/
if (QUERY_FLAG(op,FLAG_CURSED) || QUERY_FLAG(op,FLAG_DAMNED))
SET_FLAG(op,FLAG_KNOWN_CURSED);
if (op->type == POTION && op->arch != (archetype *) NULL) {
op->face = op->arch->clone.face;
free_string(op->name);
op->name = add_refcount(op->arch->clone.name);
} else if( op->type == SPELLBOOK && op->slaying != NULL){
if((op->stats.sp = look_up_spell_name( op->slaying )) <0 ){
char buf[256];
op->stats.sp = -1;
sprintf(buf, "Spell forumla for %s", op->slaying);
if(op->name != NULL)
free_string(op->name);
op->name = add_string(buf);
} else {
/* clear op->slaying since we no longer need it */
free_string(op->slaying);
op->slaying=NULL;
}
}
if (op->map) /* The shop identifies items before they hit the ground */
update_object(op);
}